﻿using SUNRPA.CONTROLS.IMPL.domain;
using SUNRPA.CONTROLS.IMPL.domain.constant;
using System.IO.Pipes;
using System.Security.Principal;
using System.Text;

namespace SUNRPA.CONTROLS.IMPL.util {
    /// <summary>
    /// 进程间管道通讯(客户端)工具类
    /// 做成单例一整个程序只能有一个客户端，只能和插件中间程序通信
    /// 若将来有多个程序通信需要改成多个客户端，但是相同的服务的连接的客户端只能有一个
    /// </summary>
    public class NamedPipeClientUtil : IDisposable {
        public static LogUtil logger = new LogUtil(typeof(NamedPipeClientUtil));
        private NamedPipeClientStream client;
        public NamedPipeClientUtil (string host, string serverName, PipeDirection pipeDirection) { 
            lock (typeof(NamedPipeClientUtil)) {
                client = new NamedPipeClientStream(host, serverName, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None);
                try { 
                    client.Connect(2000);
                    if(!client.IsConnected) {
                        throw new Exception("浏览器插件未启动！");
                    }
                }catch(Exception e) { 
                    logger.Error("请检查浏览器插件是否安装且开启", e);
                    throw new RpaBuildingException("请检查浏览器插件是否安装且开启");
                } 
                client.ReadMode = PipeTransmissionMode.Message;
            }
        }
        ~NamedPipeClientUtil() {
            try {
                client.Dispose();
            }catch(Exception e) { 
            }
        }

        public BridgeResponse SendRequest(NamePipeRequest data) {
            lock(this) { 
                WritMessage(DataUtil.ObjectJsonSerializer(data));
                string respString = ReadMessage();
                return DataUtil.DeSerializeJson<BridgeResponse>(respString);
            }
        }


        public string ReadMessage(){
            using(MemoryStream ms = new MemoryStream()) {
                byte[] buffer = new byte[0x1000];
                do {
                    ms.Write(buffer, 0, client.Read(buffer, 0, buffer.Length));
                } while(!client.IsMessageComplete);
                return Encoding.UTF8.GetString(ms.ToArray());
            }
        }

        public void WritMessage(string msg) { 
            byte[] bytes = Encoding.UTF8.GetBytes(msg);
            client.Write(bytes, 0, bytes.Length);
            client.Flush();
        }

        public void Dispose() {
            try {
                client.Dispose();
            } catch(Exception e) {
            }
        }

        public static BridgeResponse SendRequestV1(NamePipeRequest data) { 
            using(NamedPipeClientUtil client = new NamedPipeClientUtil("localhost"
                , DefaultContents.NAMED_PIPE_SERVER, PipeDirection.InOut)) { 
                BridgeResponse resp = client.SendRequest(data);
                return resp;
            }
        }
    }
}
